import org.apache.commons.lang3.StringUtils;

import java.io.*;
import java.nio.file.Files;
import java.nio.file.Path;
import java.nio.file.StandardCopyOption;
import java.util.*;
import java.util.concurrent.atomic.AtomicBoolean;
import java.util.stream.Collectors;
import java.util.stream.Stream;

public class Migration2 {
    public static void main(String[] args) throws IOException {
        System.out.println("请输入项目根路径");
        Scanner scanner = new Scanner(System.in);
        String basePath = "/Users/yangbing/IdeaProjects/OBS";
        List<Path> files = new ArrayList<>();
        searchFiles(Path.of(basePath), files);
        // 处理为 .work 文件
        for (Path file : files) {
            dealFile(file);
        }

        // 将 .work文件处理为 java文件
        for (Path file : files) {
            // 移动策略 覆盖目标文件
            Files.move(Path.of(file + ".work"), file, StandardCopyOption.REPLACE_EXISTING);
        }
    }

    private static void searchFiles(Path basePath, List<Path> filePaths) {
        if (!Files.exists(basePath)) {
            throw new RuntimeException("目录不存在[" + basePath + "]");
        }
        try (Stream<Path> list = Files.list(basePath)) {
            list.forEach(path -> {
                if (Files.isDirectory(path)) {
                    searchFiles(path, filePaths);
                } else {
                    Path fileName = path.getFileName();
                    if (fileName.toString().endsWith(".java") ||fileName.toString().endsWith(".java.vm")) {
                        filePaths.add(path);
                    }
                }
            });
        } catch (IOException e) {
            throw new RuntimeException(e);
        }
    }

    private static String specialine = "123123123123123123123123123123123";

    private static boolean dealFile(Path filePath) {
        try (BufferedReader br = Files.newBufferedReader(filePath); BufferedWriter bw = Files.newBufferedWriter(Path.of(filePath + ".work"))) {
            List<String> lines = br.lines().toList();
            List<String> mergedLine = new ArrayList<>();
            boolean hasImportSchema = false;
            boolean appendNexLine = false;
            StringBuilder newStr = new StringBuilder();
            for (String line : lines) {
                // 执行处理
                // 移除 knife4j注解 begin

                if (line.contains("com.github.xiaoymin.knife4j.annotations") || line.contains("@ApiSupport") || line.contains("@ApiOperationSupport(")) {
                    // 什么都不做
                } else if (line.matches(".*import[ ]*io.swagger.annotations.Api[ ]*;")) {
                    mergedLine.add(line.replace("io.swagger.annotations.Api", "io.swagger.v3.oas.annotations.tags.Tag"));
                } else if (line.matches(".*import[ ]*io.swagger.annotations.ApiOperation[ ]*;")) {
                    mergedLine.add(line.replace("io.swagger.annotations.ApiOperation", "io.swagger.v3.oas.annotations.Operation"));
                } else if (line.matches(".*import[ ]*io.swagger.annotations.ApiModelProperty[ ]*;")) {
                    if (!hasImportSchema) {
                        hasImportSchema = true;
                        mergedLine.add(line.replace("io.swagger.annotations.ApiModelProperty", "io.swagger.v3.oas.annotations.media.Schema"));
                    }
                } else if (line.matches(".*import[ ]*io.swagger.annotations.ApiModel[ ]*;")) {
                    if (!hasImportSchema) {
                        hasImportSchema = true;
                        mergedLine.add(line.replace("io.swagger.annotations.ApiModel", "io.swagger.v3.oas.annotations.media.Schema"));
                    }

                } else if (!line.matches(".*[(]{1}.*[)]{1}[ \\t]*[/]{0,2}.*") && (
                        line.matches(".*@Api[ ]*[(]{1}[\\S \\t]*")
                                || line.matches(".*@ApiOperation[ ]*[(]{1}[\\S \\t)]*")
                                || line.matches(".*@ApiModel[ ]*[(]{1}[\\S \\t]*")
                                || line.matches(".*@ApiModelProperty[ ]*[(]{1}[\\S \\t]*"))) {
                    newStr = new StringBuilder();
                    appendNexLine = true;
                    newStr.append(line).append("\n");
                } else {
                    if (appendNexLine) {
                        newStr.append(line);
                        if (newStr.toString().trim().endsWith(")")) {
                            mergedLine.add(newStr.toString());
                            appendNexLine = false;
                        } else {
                            newStr.append("\n");
                        }
                    } else {
                        mergedLine.add(line);
                    }
                }
            }
            mergedLine.stream().map(Migration2::dealLine).forEach(str -> {
                try {
                    bw.write(str);
                    bw.write("\n");
                } catch (IOException e) {
                    throw new RuntimeException(e);
                }
            });
        } catch (IOException e) {
            throw new RuntimeException(e);
        }
        return false;
    }

    private static String dealLine(String line) {
        if (line.matches(".*@Api[ ]*[(]{1}[\\S \\t]*")) {
            if (line.matches(".*@Api[ ]*[(]{1}[ ]*\"[\\S \\t]*\"[ ]*[)]{1}[ ]*")) {
                String value = line.substring(line.indexOf("\"") + 1, line.lastIndexOf("\""));
                return line.replace("@Api", "@Tag")
                        .replace("\"" + value + "\"", "name = \"" + value + "\"");
            } else {
                return line.replace("@Api", "@Tag")
                        .replace("tags", "name")
                        .replace("value","description");
            }
        } else if (line.matches(".*@ApiOperation[ ]*[(]{1}[\\S \\t)]*")) {
            if (line.matches(".*@ApiOperation[ ]*[(]{1}[ ]*\"[\\S \\t]*\"[ ]*[)]{1}[ ]*")) {
                String value = line.substring(line.indexOf("\"") + 1, line.lastIndexOf("\""));
                return line.replace("@ApiOperation", "@Operation")
                        .replace("\"" + value + "\"", "summary = \"" + value + "\"");
            } else {
                return line.replace("@ApiOperation", "@Operation")
                        .replace("value", "summary")
                        .replace("httpMethod", "method")
                        .replace("notes", "description");
            }
        } else if (line.matches(".*@ApiModel[ ]*[(]{1}[\\S \\t]*")) {
            if (line.matches(".*@ApiModel[ ]*[(]{1}[ ]*\"[\\S \\t]*\"[ ]*[)]{1}[ ]*")) {
                String value = line.substring(line.indexOf("\"") + 1, line.lastIndexOf("\""));
                return line.replace("@ApiModel", "@Schema")
                        .replace("\"" + value + "\"", "title = \"" + value + "\"");
            } else {
                return line.replace("@ApiModel", "@Schema")
                        .replace("value", "title")
//                        .replace("description","description")
                        .replace("discriminator", "title");
            }
        } else if (line.matches(".*@ApiModelProperty[ ]*[(]{1}[\\S \\s]*")) {
            if (line.matches(".*@ApiModelProperty[ ]*[(]{1}[ ]*\"[\\S \\t]*\"[ ]*[)]{1}[\\S\\s]*")) {
                System.out.println("matched line: " + line);
                String value = line.substring(line.indexOf("\"") + 1, line.lastIndexOf("\""));
                return line.replace("@ApiModelProperty", "@Schema")
                        .replace("\"" + value + "\"", "title = \"" + value + "\"");
            } else {
                return line.replace("@ApiModelProperty", "@Schema")
                        .replace("value", "title")
//                        .replace("required","required")
//                        .replace("description","description")
                        .replace("notes", "description")
//                        .replace("example","example")
//                        .replace("hidden","hidden")
                        .replace("dataType", "type")
//                        .replace("name","name")
                        .replace("allowableValues", "allowableValues")
                        .replace("discriminator", "title");
            }
        }
        return line;
    }

}
